package com.wy2.generator;

import cn.xo68.core.util.FileTools;
import cn.xo68.core.util.StringTools;
import com.wy2.generator.config.GeneratorConsts;
import com.wy2.generator.database.entity.DatabaseTable;
import com.wy2.generator.exception.GeneratorOutputException;
import com.wy2.generator.resource.Messages;
import com.wy2.generator.util.FreemarkerUtils;
import com.wy2.generator.util.GeneratorUtils;

import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * 基于数据库表信息的生成器
 * @author admin
 * @date 2017年12月18日下午3:26:04
 * 
 */
public class GeneratorByTable {
    private static final Logger logger=LoggerFactory.getLogger(GeneratorByTable.class);

    private final AbstractGenerator baseGenerator;
    private final String templateSuffix;
    
	/**
	 * @return the templateDirectory
	 */
	public File getTemplateDirectory() {
		return baseGenerator.getTemplateDirectory();
	}

	/**
	 * @return the outputRootDirectory
	 */
	public File getOutputRootDirectory() {
		return baseGenerator.getOutputRootDirectory();
	}
    
    public GeneratorByTable(AbstractGenerator baseGenerator) {
    	this(baseGenerator, GeneratorConsts.GENERATOR_CONFIG_TEMPLATE_SUFFIX_DEFAULT);
    }
    public GeneratorByTable(AbstractGenerator baseGenerator,String templateSuffix) {
        super();
        this.baseGenerator = baseGenerator;
        this.templateSuffix=templateSuffix;
    }
    
    /**
     * 根据数据库表结构生成
     * @date 2017-12-18 22:12:02
     * @param tables 数据表列表
     * @param model 传入模板的属性模型
     * @param override 是否覆盖生成，是的话，会覆盖原有文件
     */
    public LinkedList<GenerateResult> generate(List<DatabaseTable> tables,Map<String,Object> model,Boolean override) {
    	final List<File> templates=new ArrayList<File>();
    	searchTemplate(templates);
    	if(templates.size()<1) {
    		throw new GeneratorOutputException(Messages.getString("GeneratorOutputException.4"));
    	}
    	
    	//输出路径模板计算
    	//String outputPathTemplate=templateFilePath.substring(0, templateFilePath.length()-this.templateSuffix.length());
    	
        Map<String,Object> context=new HashMap<String, Object>();        
        context.putAll(model);
        //把基础包路径转化为文件路径 
        if(context.containsKey(GeneratorConsts.TEMPLATE_ATTRI_BASEPACKAGE)) {
            String basePackagePath=context.get(GeneratorConsts.TEMPLATE_ATTRI_BASEPACKAGE).toString().replace(".", "/");
            context.put(GeneratorConsts.TEMPLATE_ATTRI_BASEPACKAGE_PATH, basePackagePath);
        }else {
            //没有定义基础包参数
            logger.error("没有定义基础包参数： {} ", GeneratorConsts.TEMPLATE_ATTRI_BASEPACKAGE);
        }
        
        //输出路径模板计算
        List<String> outputPathTemplates=new ArrayList<String>();
        String outputPathTemplate;
        for (File template : templates) {
        	outputPathTemplate=GeneratorUtils.getOutputPathTemplateByTemplateFile(baseGenerator, template, templateSuffix);
        	outputPathTemplates.add(FreemarkerUtils.stringTemplateEncode(outputPathTemplate));
		}
        baseGenerator.initTemplateConfig(outputPathTemplates.toArray(new String[0]));
        
        
        //输出相对路径
        String relativeOutputPath;
        LinkedList<GenerateResult> generateResults=new LinkedList<GenerateResult>();
        GenerateResult generateResult;
        for (DatabaseTable databaseTable : tables) {
            
            context.put(GeneratorConsts.TEMPLATE_ATTRI_MODULE, databaseTable.getModule());
            
//            String module=databaseTable.getModule();
//            if(StringTools.isNotEmpty(module)) {
//                String basePackagePath=(String) context.get(GeneratorConsts.TEMPLATE_ATTRI_BASEPACKAGE_PATH);
//                basePackagePath=basePackagePath+"/"+module;
//                context.put(GeneratorConsts.TEMPLATE_ATTRI_BASEPACKAGE_PATH, basePackagePath);
//            }
            
            
            context.put(GeneratorConsts.TEMPLATE_ATTRI_TABLE, databaseTable);
            for (String sOutputPathTemplate : outputPathTemplates) {
            	relativeOutputPath=baseGenerator.output(sOutputPathTemplate, context, baseGenerator.getTemplateEncoding());
            	generateResult=baseGenerator.outputFile(FreemarkerUtils.stringTemplateDecode(sOutputPathTemplate)+this.templateSuffix, context, relativeOutputPath, override, baseGenerator.getTemplateEncoding());
            	generateResults.add(generateResult);
            }
        }
        return generateResults;
    }
    public LinkedList<GenerateResult> getGenerateFiles(List<DatabaseTable> tables,Map<String,Object> model) {
        final List<File> templates=new ArrayList<File>();
        searchTemplate(templates);
        if(templates.size()<1) {
            throw new GeneratorOutputException(Messages.getString("GeneratorOutputException.4"));
        }
        
        //输出路径模板计算
        //String outputPathTemplate=templateFilePath.substring(0, templateFilePath.length()-this.templateSuffix.length());
        
        Map<String,Object> context=new HashMap<String, Object>();        
        context.putAll(model);
        //把基础包路径转化为文件路径 
        if(context.containsKey(GeneratorConsts.TEMPLATE_ATTRI_BASEPACKAGE)) {
            String basePackagePath=context.get(GeneratorConsts.TEMPLATE_ATTRI_BASEPACKAGE).toString().replace(".", "/");
            context.put(GeneratorConsts.TEMPLATE_ATTRI_BASEPACKAGE_PATH, basePackagePath);
        }else {
            //没有定义基础包参数
            logger.error("没有定义基础包参数： {} ", GeneratorConsts.TEMPLATE_ATTRI_BASEPACKAGE);
        }
        
        //输出路径模板计算
        String outputPathTemplate;
        
        List<StringTemplate> stringTemplates=new ArrayList<>();
        StringTemplate stringTemplate=null;
        for (File template : templates) {
            outputPathTemplate=GeneratorUtils.getOutputPathTemplateByTemplateFile(baseGenerator, template, templateSuffix);
            //outputPathTemplates.add(FreemarkerUtils.stringTemplateEncode(outputPathTemplate));
            
            stringTemplate=new StringTemplate(outputPathTemplate, outputPathTemplate);
            stringTemplates.add(stringTemplate);
        }
        baseGenerator.initTemplateConfig();
        
        StringGenerator stringGenerator=new StringGenerator(baseGenerator.getTemplateEncoding());
        stringGenerator.initTemplateConfig(stringTemplates.toArray(new StringTemplate[0]));
        
        
        //输出相对路径
        String relativeOutputPath=null;
        LinkedList<GenerateResult> generateResults=new LinkedList<GenerateResult>();
        GenerateResult generateResult;
        for (DatabaseTable databaseTable : tables) {
            
            context.put(GeneratorConsts.TEMPLATE_ATTRI_MODULE, databaseTable.getModule());            
            context.put(GeneratorConsts.TEMPLATE_ATTRI_TABLE, databaseTable);
            for (StringTemplate fStringTemplate : stringTemplates) {
                try {
                    relativeOutputPath=stringGenerator.getStringResult(fStringTemplate.getName(), context);
                } catch (Exception e) {
                    logger.error("模板输出路径合成异常", e);
                }
                if(StringTools.isNotEmpty(relativeOutputPath)) {
                    generateResult=new GenerateResult(databaseTable.getSqlName(), relativeOutputPath, true);
                    
                }else {
                    generateResult=new GenerateResult(databaseTable.getSqlName(), fStringTemplate.getName(), false);
                }
                generateResults.add(generateResult);
            }
        }
        return generateResults;
    }
    
    
    private void searchTemplate(final List<File> templates) {
    	FileTools.searchFile(templates, baseGenerator.getTemplateDirectory(), this.templateSuffix);
    }
}
